﻿using Microsoft.Win32;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
//using System.IO.Compression;
using System.Linq;
using System.Windows;
using Ionic.Zip;
using WK.Libraries.BetterFolderBrowserNS;
using System.Windows.Forms;
using System.Text;

//Shared lib should be referenced by link.
namespace KaroglanSharedLib
{
    public static class Utils
    {
        public static string BaseWorkSpace = "";

        public static bool IsLocationValid()
        {
            bool hasModFolder = Directory.Exists(GetModsFolder());
            return hasModFolder;
        }

        public static string GetBaseFolder()
        {
            if (string.IsNullOrEmpty(BaseWorkSpace))
            {
                return Environment.CurrentDirectory;
            }
            else return BaseWorkSpace;
        }
        public static string GetModsFolder()
        {
            return Path.Combine(GetBaseFolder(), @".minecraft\versions\Karoglan-TFC-Create\mods");
        }

        public static string GetOptionPath()
        {
            return Path.Combine(GetBaseFolder(), @".minecraft\versions\Karoglan-TFC-Create\options.txt");
        }

        public static string GetOptionPathBK()
        {
            return GetOptionPath().Replace(".txt", "_high.txt");
        }

        public static void RecoverOption()
        {
            File.Copy(GetOptionPathBK(), GetOptionPath(), true);
        }

        public static string GetModFullPath(string fileName)
        {
            return Directory.GetFiles(GetModsFolder(),$"{fileName}*", SearchOption.AllDirectories).FirstOrDefault();
        }

        public static string GetToolsFolder()
        {
            var toolsFolder = Path.Combine(GetBaseFolder(), "tools");
            if (!Directory.Exists(toolsFolder))
            {
                Directory.CreateDirectory(toolsFolder);
            }
            return toolsFolder;
        }

        public static string GetTempFolder()
        {
            var toolsFolder = Path.Combine(GetBaseFolder(), "temp");
            if (!Directory.Exists(toolsFolder))
            {
                Directory.CreateDirectory(toolsFolder);
            }
            return toolsFolder;
        }

        public static void CopyFileToDestination(string sourceFilePath, string destFilePath)
        {
            // 获取目标文件的目录路径
            string destDirectory = Path.GetDirectoryName(destFilePath);

            // 检查目标目录是否存在
            if (!Directory.Exists(destDirectory))
            {
                // 如果目标目录不存在，则创建它
                Directory.CreateDirectory(destDirectory);
            }
            // 现在，目标目录存在，可以执行文件复制
            File.Copy(sourceFilePath, destFilePath, overwrite: false);
        }

        public static FileChangeState AreFilesDifferent(string relativePath, string oldFilePath, string newFilePath)
        {
            const int bufferSize = 1024 * 1024; // 比如，一次读取1MB。

            // var oldFilePath = GetAbsolutePath(cfg.oldPath, relativePath);
            // var newFilePath = GetAbsolutePath(cfg.newPath, relativePath);

            if (File.Exists(oldFilePath) && !File.Exists(newFilePath))
                return FileChangeState.Deleted;
            else if (File.Exists(newFilePath) && !File.Exists(oldFilePath))
                return FileChangeState.Added;
            else if (!File.Exists(oldFilePath) && !File.Exists(newFilePath))
            {
                string errorMsg = $"错误：新、旧文件夹中都无法找到[{relativePath}]\n" +
                    $"其中，解析出来的OldFilePath为{oldFilePath}\n" +
                    $"其中，解析出来的NewFilePath为{newFilePath}";
                // MessageBox.Show(errorMsg);
                Exception e = new Exception(errorMsg);
                throw e;
            }

            FileInfo fileInfo1 = new FileInfo(oldFilePath);
            FileInfo fileInfo2 = new FileInfo(newFilePath);

            // 先检查文件大小
            if (fileInfo1.Length != fileInfo2.Length)
            {
                return FileChangeState.Modified;
            }

            // 逐块对比两个文件
            byte[] buffer1 = new byte[bufferSize];
            byte[] buffer2 = new byte[bufferSize];

            using (FileStream fs1 = fileInfo1.OpenRead())
            using (FileStream fs2 = fileInfo2.OpenRead())
            {
                while (true)
                {
                    int bytesRead1 = fs1.Read(buffer1, 0, buffer1.Length);
                    int bytesRead2 = fs2.Read(buffer2, 0, buffer2.Length);

                    // 比较读取的字节数
                    if (bytesRead1 != bytesRead2)
                    {
                        return FileChangeState.Modified;
                    }

                    // 如果到达文件尾，停止比较
                    if (bytesRead1 == 0)
                    {
                        break;
                    }

                    // 逐字节比较
                    for (int i = 0; i < bytesRead1; i++)
                    {
                        if (buffer1[i] != buffer2[i])
                        {
                            return FileChangeState.Modified;
                        }
                    }
                }
            }

            // 文件相同
            return FileChangeState.Unchanged;
        }

        public static bool IsPathUnderDirectory(string childPath, string parentDirectoryPath)
        {
            // Get the full path (absolute path and normalized)
            var childFullPath = Path.GetFullPath(childPath);
            var parentFullPath = Path.GetFullPath(parentDirectoryPath);

            // Ensure the parent directory path ends with a directory separator
            // to avoid partial matches (e.g., "C:\Folder" and "C:\FolderSub").
            if (!parentFullPath.EndsWith(Path.DirectorySeparatorChar.ToString(), StringComparison.Ordinal))
            {
                parentFullPath += Path.DirectorySeparatorChar;
            }

            // Use StringComparison.OrdinalIgnoreCase for case-insensitive comparison,
            // which is generally the default behavior on Windows file systems (NTFS and FAT).
            return childFullPath.StartsWith(parentFullPath, StringComparison.OrdinalIgnoreCase);
        }
        // 获取绝对路径B在绝对路径A中的相对路径C
        public static string GetRelativePath(string absolutePathA, string absolutePathB)
        {
            // 确保absolutePathA是一个目录
            string directoryPathA = absolutePathA;
            if (!Directory.Exists(absolutePathA))
            {
                directoryPathA = Path.GetDirectoryName(absolutePathA);
            }

            // 如果路径不以目录分隔符结尾，添加它
            if (!directoryPathA.EndsWith(Path.DirectorySeparatorChar.ToString()))
            {
                directoryPathA += Path.DirectorySeparatorChar;
            }

            Uri baseUri = new Uri(directoryPathA);
            Uri targetUri = new Uri(absolutePathB);
            Uri relativeUri = baseUri.MakeRelativeUri(targetUri);
            string relativePath = Uri.UnescapeDataString(relativeUri.ToString()).Replace('/', Path.DirectorySeparatorChar);
            return relativePath;
        }

        // 通过相对路径C获取其相对于绝对路径A的绝对路径B
        public static string GetAbsolutePath(string absolutePathA, string relativePathC)
        {
            return Path.Combine(absolutePathA, relativePathC);
        }

        public static void CreateZip(string sourceDirectory, string zipFilePath)
        {
            using (ZipFile zip = new ZipFile())
            {
                zip.MaxOutputSegmentSize = 100 * 1000 * 1000;
                zip.AlternateEncoding = Encoding.UTF8;
                zip.AlternateEncodingUsage = ZipOption.Always;
                zip.AddDirectory(sourceDirectory);
                zip.Save(zipFilePath);
            }
        }

        public static bool ExtractZip(string zipFilePath, string extractionPath)
        {
            try
            {
                // 确保解压目录存在
                if (!Directory.Exists(extractionPath))
                {
                    Directory.CreateDirectory(extractionPath);
                }

                using (ZipFile zipEntries = new ZipFile(zipFilePath))
                {
                    zipEntries.ExtractAll(extractionPath);
                }
                return true;
            }
            catch (Exception e)
            {
                Error($"解压失败：\n{e.Message}");
                return false;
            }
        }

        public static MessageBoxResult Error(string info)
        {
            return System.Windows.MessageBox.Show($"{info}", "错误", MessageBoxButton.OK, MessageBoxImage.Error);
        } 
        public static bool SelectFileInExpoler(string path)
        {
            if (File.Exists(path) || Directory.Exists(path))
            {
                Process.Start("explorer.exe", $"/select,\"{path}\"");
                return true;
            }
            return false;
        }

        public static bool IsX64System()
        {
            return Environment.Is64BitOperatingSystem;
        }
        
        public static bool GetJavaPath(out string javaPath)
        {
            javaPath = "";
            RegistryKey java = Registry.LocalMachine.OpenSubKey("SOFTWARE")?.OpenSubKey("JavaSoft")?.OpenSubKey("JDK");
            if (java != null)
            {
                string[] javaVersions = java.GetSubKeyNames();
                foreach (var javaVer in javaVersions)
                {
                    javaPath = java.OpenSubKey(javaVer).GetValue("JavaHome").ToString();
                    return true;
                }
            }
            return false;
        }
        
        public static bool ArePathsPointingToSameFile(string path1, string path2)
        {
            // 创建文件信息对象
            var fileInfo1 = new FileInfo(path1);
            var fileInfo2 = new FileInfo(path2);

            // 获取规范路径名
            var fullPath1 = fileInfo1.FullName;
            var fullPath2 = fileInfo2.FullName;

            // 比较规范路径
            if (String.Compare(fullPath1, fullPath2, StringComparison.OrdinalIgnoreCase) != 0)
                return false;

            // 检查文件是否存在
            if (!fileInfo1.Exists || !fileInfo2.Exists)
                return false;

            // 比较文件的基本属性
            return fileInfo1.Length == fileInfo2.Length && fileInfo1.LastWriteTime == fileInfo2.LastWriteTime;
        }
    }


    public enum FileChangeState
    {
        Unchanged,
        Deleted,
        Added,
        Modified
    }
}
